| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import type { ReactNode, JSX } from 'react';
- import React, { useEffect } from 'react';
- import type {
- GetServerSideProps, GetServerSidePropsContext,
- } from 'next';
- import dynamic from 'next/dynamic';
- import Head from 'next/head';
- import { ShareLinkLayout } from '~/components/Layout/ShareLinkLayout';
- import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
- import { ShareLinkPageView } from '~/components/ShareLinkPageView';
- import type { CommonEachProps } from '~/pages/common-props';
- import { NextjsRoutingType, detectNextjsRoutingType } from '~/pages/utils/nextjs-routing-utils';
- import { useCustomTitleForPage } from '~/pages/utils/page-title-customization';
- import { useIsSearchPage, useIsSharedUser } from '~/states/context';
- import {
- useCurrentPageData, useCurrentPagePath,
- } from '~/states/page';
- import { useHydratePageAtoms } from '~/states/page/hydrate';
- import { useDisableLinkSharing, useRendererConfig } from '~/states/server-configurations';
- import loggerFactory from '~/utils/logger';
- import type { NextPageWithLayout } from '../../_app.page';
- import type { GeneralPageInitialProps } from '../../general-page';
- import { useInitialCSRFetch } from '../../general-page';
- import { registerPageToShowRevisionWithMeta } from '../../general-page/superjson';
- import { useHydrateServerConfigurationAtoms } from '../../general-page/use-hydrate-server-configurations';
- import { NEXT_JS_ROUTING_PAGE } from './consts';
- import { getServerSidePropsForInitial, getServerSidePropsForSameRoute } from './server-side-props';
- import type { ShareLinkInitialProps } from './types';
- // call superjson custom register
- registerPageToShowRevisionWithMeta();
- const GrowiContextualSubNavigation = dynamic(() => import('~/client/components/Navbar/GrowiContextualSubNavigation'), { ssr: false });
- const logger = loggerFactory('growi:next-page:share');
- type InitialProps = CommonEachProps & GeneralPageInitialProps & ShareLinkInitialProps;
- type Props = CommonEachProps | InitialProps;
- const isInitialProps = (props: Props): props is InitialProps => {
- return 'isNextjsRoutingTypeInitial' in props && props.isNextjsRoutingTypeInitial;
- };
- const SharedPage: NextPageWithLayout<Props> = (props: Props) => {
- // Initialize Jotai atoms with initial data - must be called unconditionally
- const shareLink = isInitialProps(props) ? props.shareLink : undefined;
- const isExpired = isInitialProps(props) ? props.isExpired : undefined;
- const pageData = isInitialProps(props) ? props.pageWithMeta?.data : undefined;
- useHydratePageAtoms(pageData, {
- shareLinkId: shareLink?._id,
- });
- const [currentPage] = useCurrentPageData();
- const [currentPagePath] = useCurrentPagePath();
- const [rendererConfig] = useRendererConfig();
- const [, setIsSharedUser] = useIsSharedUser();
- const [, setIsSearchPage] = useIsSearchPage();
- const [isLinkSharingDisabled] = useDisableLinkSharing();
- // Use custom hooks for navigation and routing
- // useSameRouteNavigation();
- // If initial props and skipSSR, fetch page data on client-side
- useInitialCSRFetch(isInitialProps(props) && props.skipSSR);
- // Initialize atom values
- useEffect(() => {
- setIsSharedUser(true);
- setIsSearchPage(false);
- }, [setIsSharedUser, setIsSearchPage]);
- // If the data on the page changes without router.push, pageWithMeta remains old because getServerSideProps() is not executed
- // So preferentially take page data from useSWRxCurrentPage
- const pagePath = currentPagePath ?? props.currentPathname;
- const title = useCustomTitleForPage(pagePath);
- return (
- <>
- <Head>
- <title>{title}</title>
- </Head>
- <div className="dynamic-layout-root justify-content-between">
- <GrowiContextualSubNavigation currentPage={currentPage} />
- <ShareLinkPageView
- pagePath={pagePath}
- rendererConfig={rendererConfig}
- shareLink={shareLink}
- isExpired={isExpired}
- disableLinkSharing={isLinkSharingDisabled}
- />
- </div>
- </>
- );
- };
- type LayoutProps = Props & {
- children?: ReactNode
- }
- const Layout = ({ children, ...props }: LayoutProps): JSX.Element => {
- // Hydrate sidebar atoms with server-side data - must be called unconditionally
- const initialProps = isInitialProps(props) ? props : undefined;
- useHydrateServerConfigurationAtoms(initialProps?.serverConfig, initialProps?.rendererConfig);
- return <ShareLinkLayout>{children}</ShareLinkLayout>;
- };
- SharedPage.getLayout = function getLayout(page) {
- return (
- <>
- <DrawioViewerScript drawioUri={page.props.rendererConfig.drawioUri} />
- <Layout {...page.props}>
- {page}
- </Layout>
- </>
- );
- };
- // function getAction(props: Props): SupportedActionType {
- // let action: SupportedActionType;
- // if (props.isExpired) {
- // action = SupportedAction.ACTION_SHARE_LINK_EXPIRED_PAGE_VIEW;
- // }
- // else if (props.shareLink == null) {
- // action = SupportedAction.ACTION_SHARE_LINK_NOT_FOUND;
- // }
- // else {
- // action = SupportedAction.ACTION_SHARE_LINK_PAGE_VIEW;
- // }
- // return action;
- // }
- export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
- // detect Next.js routing type
- const nextjsRoutingType = detectNextjsRoutingType(context, NEXT_JS_ROUTING_PAGE);
- if (nextjsRoutingType === NextjsRoutingType.INITIAL) {
- return getServerSidePropsForInitial(context);
- }
- // Lightweight props for same-route navigation
- return getServerSidePropsForSameRoute(context);
- };
- export default SharedPage;
|